#include <iostream>
#include <cstring>
#include <cmath>

#define x first
#define y second

using namespace std;

typedef pair<double, double> PDD;

const int N = 160;
const double INF = 1e18;

int n;

PDD q[N];

double g[N][N];
double dist[N];

double get_dist(PDD a, PDD b)
{
	return sqrt((b.x - a.x) * (b.x - a.x) + (b.y - a.y) * (b.y - a.y));
}

void floyd()
{
	for (int k = 1; k <= n; k ++ )
	{
		for (int i = 1; i <= n; i ++ )
		{
			for (int j = 1; j <= n; j ++ )
			{
				g[i][j] = min(g[i][k] + g[k][j], g[i][j]);
			}
		}
	}
}

int main()
{
	cin >> n;
	
	for (int i = 1; i <= n; i ++ )
	{
		double a, b;
		cin >> a >> b;
		
//		cout << a << "====" << b << endl;
		q[i] = {a, b};
	}
	
//	memset(g, 0x3f, sizeof g);

	for (int i = 1; i <= n; i ++ )
		for (int j = 1; j <= n; j ++ ) 
			g[i][j] = INF;
	
	for (int i = 1; i <= n; i ++ ) g[i][i] = 0;
	
	
	for (int i = 1; i <= n; i ++ )
	{
		for (int j = 1; j <= n; j ++ )
		{
			char c;
			cin >> c;
//			cout << c << "======";
			if (c == '1') g[i][j] = get_dist(q[i], q[j]);
		}
//		puts("");
	}
	
	floyd();
	
	double max1 = 0;
	
	for (int i = 1; i <= n; i ++ )
	{
		for (int j = 1; j <= n; j ++ )
		{
			if (g[i][j] > INF / 2) continue;
			
			dist[i] = max(dist[i], g[i][j]);
		}
		
		max1 = max(dist[i], max1);
	}
	
	double max2 = INF;
	
	
	
	for (int i = 1; i <= n; i ++ )
	{
		for (int j = 1; j <= n; j ++ )
		{
			if (g[i][j] < INF / 2) continue;
//			cout << g[i][j] << endl;		
			max2 = min(max2, get_dist(q[i], q[j]) + dist[i] + dist[j]);
		}
	}
	
//	cout << max(max2, max1) << endl;

	printf("%.6lf", max(max2, max1));
	
	return 0;
}
//5
//0 0
//0 1
//1 0
//100 100
//200 200
//00000
//00100
//01000
//00001
//00010